var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/businessComponent/Attachment/components/Upload.tsx
var Upload_exports = {};
__export(Upload_exports, {
  Upload: () => Upload
});
module.exports = __toCommonJS(Upload_exports);
var import_antd = require("antd");
var import_react = require("react");
var import_util = require("../../../util");
var import_AttachmentContext = require("../AttachmentContext");
var import_util2 = require("../util");
var defaultUploadState = {
  success: 0,
  fail: 0,
  error: 0,
  all: 0,
  progress: {}
};
var AsyncPoolUpload = class {
  constructor(limit = 3, chunkSize = 5242880, retry = 3) {
    this.limit = limit;
    this._chunkSize = chunkSize;
    this._retry = retry;
  }
  async upload(file, options) {
    const { upload, mergeChunks, onChunkUploadSuccess: _onChunkUploadSuccess } = options;
    return new Promise(async (resolve, reject) => {
      try {
        const identifier = await (0, import_util2.getFileMd5BySlice)(file, this._chunkSize);
        const chunks = this._createFileChunk(file, identifier);
        let uploadedChunkNumber = 0;
        const onChunkUploadSuccess = (value) => {
          uploadedChunkNumber++;
          if (uploadedChunkNumber === chunks.length) {
            if (chunks.length === 1) {
              _onChunkUploadSuccess == null ? void 0 : _onChunkUploadSuccess(value);
              resolve();
            } else {
              mergeChunks(identifier, chunks.length).then((res) => {
                if (!res.fileId) {
                  reject("文件合并失败");
                } else {
                  _onChunkUploadSuccess == null ? void 0 : _onChunkUploadSuccess(value);
                  resolve();
                }
              }).catch((err) => reject(err));
            }
          } else {
            _onChunkUploadSuccess == null ? void 0 : _onChunkUploadSuccess(value);
          }
        };
        await this._uploadChunks(chunks, upload, onChunkUploadSuccess);
      } catch (error) {
        reject(error);
      }
    });
  }
  _createFileChunk(file, identifier) {
    let cur = 0;
    const chunkList = [];
    while (cur < file.size) {
      const sliceFile = file.slice(cur, cur + this._chunkSize);
      chunkList.push(sliceFile);
      cur += this._chunkSize;
    }
    return chunkList.map((chunk, index) => ({
      file: chunk,
      chunkNumber: index + 1,
      chunkSize: this._chunkSize,
      currentChunkSize: chunk.size,
      totalChunks: chunkList.length,
      totalSize: file.size,
      md5: identifier,
      fileName: file.name
    }));
  }
  async _uploadChunks(chunkList, upload, onChunkUploadSuccess, retry = this._retry) {
    if (retry < 0) {
      return Promise.reject(chunkList[0].fileName);
    }
    const uploadSuccessChunk = [true];
    await (0, import_util2.asyncPool)(chunkList, this.limit, async (value) => {
      try {
        await upload(value);
        uploadSuccessChunk[value.chunkNumber] = true;
        onChunkUploadSuccess && onChunkUploadSuccess(value);
      } catch (error) {
        if (error.name === "api") {
          return Promise.reject(value.fileName);
        }
      }
    });
    const failedUploadChunkList = chunkList.filter((v) => !uploadSuccessChunk[v.chunkNumber]);
    return failedUploadChunkList.length ? this._uploadChunks(failedUploadChunkList, upload, onChunkUploadSuccess, retry - 1) : Promise.resolve();
  }
};
var Upload = (0, import_react.forwardRef)((props, ref) => {
  const {
    accept = "*",
    children = /* @__PURE__ */ React.createElement(import_antd.Button, { type: "primary" }, "上传文件"),
    hidden = false,
    containerStyles = {},
    onBeforeUpload,
    onUploaded,
    onUploadStateChange,
    ...rest
  } = props;
  const { upload, mergeChunks, uploadThreadCount, chunkSize } = (0, import_AttachmentContext.useAttachment)();
  const asyncPoolUpload = (0, import_react.useMemo)(
    () => new AsyncPoolUpload(uploadThreadCount, chunkSize),
    [uploadThreadCount, chunkSize]
  );
  const uploadStateRef = (0, import_react.useRef)(defaultUploadState);
  const changeUploadState = (0, import_util.useRefCallback)((nextState) => {
    uploadStateRef.current = nextState;
    const { success, fail, all, error } = nextState;
    const completed = success + fail + error === all;
    onUploadStateChange == null ? void 0 : onUploadStateChange(nextState, !completed);
  });
  const uploadFile = (0, import_util.useRefCallback)(async (file) => {
    try {
      await asyncPoolUpload.upload(file, {
        upload,
        mergeChunks,
        onChunkUploadSuccess: (data) => {
          const fileProcess = uploadStateRef.current.progress[data.fileName];
          const nextSize = ((fileProcess == null ? void 0 : fileProcess.uploadedSize) || 0) + data.currentChunkSize;
          const percent = Math.floor(nextSize / data.totalSize * 100);
          changeUploadState({
            ...uploadStateRef.current,
            progress: {
              ...uploadStateRef.current.progress,
              [data.fileName]: {
                fileSize: data.totalSize,
                fileName: data.fileName,
                uploadedSize: nextSize,
                percent,
                status: percent === 100 ? "done" : "uploading"
              }
            }
          });
        }
      });
      changeUploadState({
        ...uploadStateRef.current,
        success: uploadStateRef.current.success + 1
      });
      onUploaded && onUploaded(file);
    } catch (error) {
      changeUploadState({
        ...uploadStateRef.current,
        fail: uploadStateRef.current.fail + 1,
        progress: {
          ...uploadStateRef.current.progress,
          [file.name]: {
            ...uploadStateRef.current.progress[file.name],
            status: "fail"
          }
        }
      });
    }
  });
  return /* @__PURE__ */ React.createElement(
    "div",
    {
      style: {
        ...containerStyles,
        display: hidden ? "none" : containerStyles.display || "inline-block"
      }
    },
    /* @__PURE__ */ React.createElement(
      import_antd.Upload,
      {
        ref,
        multiple: true,
        accept,
        maxCount: 1,
        showUploadList: false,
        beforeUpload: async (file, fileList) => {
          let error = 0;
          if (onBeforeUpload) {
            const checked = await onBeforeUpload(file, fileList);
            error = checked ? 0 : 1;
          }
          const fileProcess = {
            fileSize: file.size,
            fileName: file.name,
            uploadedSize: 0,
            percent: file.size > chunkSize ? 0 : Math.floor(Math.random() * 20) + 30,
            status: error === 1 ? "error" : "uploading"
          };
          const nextState = file === fileList[0] ? {
            ...defaultUploadState,
            all: fileList.length,
            error,
            progress: {
              [file.name]: fileProcess
            }
          } : {
            ...uploadStateRef.current,
            error: uploadStateRef.current.error + error,
            progress: {
              ...uploadStateRef.current.progress,
              [file.name]: fileProcess
            }
          };
          changeUploadState(nextState);
          if (error === 1) {
            return false;
          }
          await uploadFile(file);
          return false;
        },
        children,
        ...rest
      }
    )
  );
});
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  Upload
});
